/**
 * 图片懒加载jQuery插件
 *
 * 2019-07-25
 * CoderMonkie
 */

(function(){

    // 配置信息
    var options = {}

    /**
     * 默认配置
     */
    function defaultOptions(){
        return {
            preOffset: 100,
            container: window
        }
    }
    
    // 扩展 lazyLoad 方法
    $.fn.extend({
        lazyLoad: function(setting){
            var that = this

            options = defaultOptions()

            // 确保参数合法的情况下
            if(setting && toString.call(setting) === '[object Object]') {

                // 确保参数里设定项目的值的类型正确
                //   preOffset：数值(负数没有意义，NaN更不符合要求： >= 0)
                //   container：DOM元素

                if(setting.preOffset && typeof(setting.preOffset) === 'number' && setting.preOffset >= 0){
                    options.preOffset = setting.preOffset;
                }

                if(setting.container && setting.container.nodeType){
                    options.container = setting.container
                }
            }

            // 初始化时加载一次进入可视区域的图片
            showRealImage(this)

            // 滚动条拖动时显示未加载且进入（即将进入）可视区域的图片
            $(options.container).scroll(()=>{
                showRealImage(that)
            })
        }
    })

    /**
     *修改进入可视区域的图像元素的真实图像地址使之显示
     *
     * @param {*} $eleList
     */
    function showRealImage($eleList){
        if(!$eleList || !$eleList.length){
            return
        }

        // 先过滤，后处理
        $eleList.filter((i, ele)=>{
            var $img = $(ele)
            // 作为处理对象的条件：
            //    1.未加载
            //    2.进入可视区域
            //    3.DOM标签为img
            return !$img.attr('loaded') && isInSight($img) && ele.nodeName.toLowerCase() === 'img'
        }).each(function(i,ele){
            var $img = $(ele)
            var source = $img.data('lazysrc')
            if(source){
                // 显示真实图片
                $img.attr('src', source)
            }
            // 设为已加载，之后不再需要处理
            $img.attr('loaded', true)
        })
        
        /**
         *判断图像元素是否进入可视区域（包含预加载Offset的距离）
        *
        * @param {*} $node
        */
        function isInSight($node){
            return ($node.offset().top - options.preOffset) <= $(options.container).height() + $(options.container).scrollTop();
        }
    }
})()